'use strict';

function tableData(options) {
	var that = this;

	that.options = options;
	that._columns = new obj_column(that.options);
	that._data = new obj_data(that.options.idField);
	that._errors = new obj_errors();
	that._p_errors = new obj_p_errors();
	that._editedCells = new obj_editedCells();

	resetVariables();

	function resetVariables() {
		that._data.resetData();
		that._editedCells.resetData();
		that._errors.resetData();
		that._p_errors.resetData();
	}

	function obj_column(options) {
		this.setData = function(data) {
			if(!data) {
				return;
			}

			$.each(data, function(i, col) {
				if(options.ignoreVisible) {
					col.visible = true;
				}
			});

			this.oriData = data;
			this.data = [];
			$.extend(true, this.data, this.oriData);

			if(options.columnFormatter) {
				var thisData = this.data;
				$.each(options.columnFormatter, function(k, val) {
					$.each(thisData, function(i, col) {
						if(k == col.title) {
							col.formatter = val;
							return true;
						}
					});
				});
			}

			if(options.operate) {
				options.operate.disable = true;
				this.data.push(options.operate);
			}

			if(options.locate) {
				options.locate.disable = true;
				this.data.push(options.locate);
			}

			var colSource = {};
			var colMath = [];
			var oriData = this.oriData;
			$.each(oriData, function(i, col) {
				if(col.source && col.source.length) {
					colSource[col.title] = {};
					$.each(col.source, function(k, val) {
						colSource[col.title][val.id] = val.text;
					});
				}

				if(col.math) {
					var ret = parseMath(col.math, oriData, options.POSITION_SPLIT);
					if(ret) {
						$.each(ret, function(k, val) {
							colMath.push(val);
						});
					}
				}
			});

			this.colSource = colSource;
			this.colMath = colMath;
			this.triggerPropertyChange(this.data);
		}

		/*只有构建table时增加checkbox和主键字段用到*/
		this.spliceData = function(index, item) {
			this.data.splice(index, 0, item);
		}

		this.triggerPropertyChange = function(value) {
			resetVariables();
			initColumn(value, options);

			if(this.propertyChange) {
				this.propertyChange(value);
			}
		}
	};

	function obj_data(idField) {
		/*table和report装载新数据时调用*/
		this.setData = function(json, submitted) {
			this.allData = json;
			this.submitData = {};
			if(!submitted) {
				var subdata = this.submitData;
				$.each(json, function(k, val) {
					subdata[val[idField]] = val;
					delete subdata[val[idField]]['-'];
				});
			}
			this.submitted = submitted;
			this.triggerPropertyChange(this.submitData);
		}
		/*table插入数据时调用*/
		this.insertData = function(items) {
			var thisdata = this.allData;
			var subdata = this.submitData;
			$.each(items, function(k, item) {
				thisdata.push(item);
				subdata[item[idField]] = item;
				delete subdata[item[idField]]['-'];
			});

			this.submitted = false;
			this.triggerPropertyChange(this.submitData);
		}
		/*table和report新增或修改记录时调用*/
		this.pushData = function(item) {
			var thisdata = this.allData;
			var subdata = this.submitData;
			var isExist = false;
			$.each(thisdata, function(k, val) {
				if(item[idField] == val[idField]) {
					isExist = true;
					thisdata[k] = item;
					$.each(subdata, function(i, v) {
						if(item[idField] == v[idField]) {
							subdata[item[idField]] = item;
							delete subdata[item[idField]]['-'];
							return false;
						}
					});
					return false;
				}
			});

			if(!isExist) {
				this.allData.push(item);
				this.submitData[item[idField]] = item;
				delete subdata[item[idField]]['-'];
				this.submitted = false;
			}

			this.triggerPropertyChange(this.submitData);
		}

		this.spliceData = function(id, field, value) {
			var thisdata = this.allData;
			$.each(thisdata, function(k, val) {
				if(id == val[idField]) {
					thisdata[field] = value;
					return false;
				}
			});
			if(this.submitData[id]) {
				this.submitData[id][field] = value;
			}

			this.triggerPropertyChange(this.submitData);
		}

		this.removeData = function(id) {
			var thisdata = this.allData;
			var subdata = this.submitData;
			var isExist = false;
			for(var i = thisdata.length - 1; i >= 0; i--) {
				if(id == thisdata[i][idField]) {
					thisdata.splice(i, 1);
					delete subdata[id];
					isExist = true;
					break;
				}
			}
			if(Object.getOwnPropertyNames(this.submitData).length == 0) {
				this.submitted = true;
			}

			if(isExist) {
				this.triggerPropertyChange(this.submitData);
			}
		}

		this.doSubmit = function() {
			this.submitData = {};
			this.submitted = true;
			this.triggerPropertyChange(this.submitData);
		}

		this.resetData = function() {
			this.allData = [];
			this.submitData = {};
			this.submitted = true;
			this.triggerPropertyChange(this.submitData);
		}

		this.triggerPropertyChange = function(value) {
			if(this.propertyChange) {
				this.propertyChange(value);
			}
		}
	}

	function obj_errors() {
		this.pushDatas = function(items) {
			var thisdata = this.data;
			$.each(items, function(i, item) {
				var isExist = false;
				$.each(thisdata, function(k, val) {
					if(item.row == val.row && item.col == val.col) {
						isExist = true;
						thisdata[k] = item;
						return false;
					}
				});
				if(!isExist) {
					thisdata.push(item);
				}
			});

			this.triggerPropertyChange(this.data);
		}

		this.removeData = function(row, col) {
			var thisdata = this.data;
			var spliced = false;
			for(var i = thisdata.length - 1; i >= 0; i--) {
				if(row == thisdata[i].row && (col && col == thisdata[i].col || !col)) {
					thisdata.splice(i, 1);
					spliced = true;
					break;
				}
			}
			if(spliced) {
				this.triggerPropertyChange(this.data);
			}
		}

		this.resetData = function(silent) {
			this.data = [];
			if(!silent) {
				this.triggerPropertyChange(this.data);
			}
		}

		this.triggerPropertyChange = function(value) {
			if(this.propertyChange) {
				this.propertyChange(value);
			}
		}
	}

	function obj_editedCells() {
		this.pushData = function(item) {
			//如果改变未提交数据项，则不计入
			var inSubmitData = false;
			$.each(that._data.submitData, function(k, val) {
				if(item.F_ID == val[that.options.idField]) {
					inSubmitData = true;
					return false;
				}
			});
			if(inSubmitData) {
				return;
			}

			var isExist = false;
			var thatdata = this.data;
			$.each(thatdata, function(k, val) {
				if(item.F_ID == val.F_ID && item.F_TEXT == val.F_TEXT) {
					isExist = true;
					thatdata[k] = item;
					return false;
				}
			});
			if(!isExist) {
				thatdata.push(item);
			}

			this.triggerPropertyChange(this.data);
		}
		/*有改变和删除两个作用*/
		this.spliceData = function(id, name) {
			var spliced = false;
			var thatdata = this.data;
			for(var i = thatdata.length - 1; i >= 0; i--) {
				if(id == thatdata[i].F_ID && (name && name == thatdata[i].F_TEXT || !name)) {
					thatdata.splice(i, 1);
					spliced = true;
				}
			}
			if(spliced) {
				this.triggerPropertyChange(this.data);
			}
		}

		this.resetData = function() {
			this.data = [];
			this.additionData = []; //report提交表头数据使用
			this.triggerPropertyChange(this.data);
		}

		this.triggerPropertyChange = function(value) {
			if(this.propertyChange) {
				this.propertyChange(value);
			}
		}
	}

	function obj_p_errors() {
		this.toNext = function() {
			this.data++;
			this.triggerPropertyChange(this.data);
		}
		this.toPrevious = function() {
			this.data--;
			this.triggerPropertyChange(this.data);
		}
		this.goto = function(index) {
			this.data = index;
			this.triggerPropertyChange(this.data);
		}
		this.resetData = function() {
			this.data = -1;
			this.triggerPropertyChange(this.data);
		}

		this.triggerPropertyChange = function(value) {
			if(this.propertyChange) {
				this.propertyChange(value);
			}
		}
	}

	function initColumn(columnData, options) {
		var firstVisibleFlag = false;
		var lastVisible = columnData.length - 1;
		for(var i = columnData.length - 1; i >= 0; i--) {
			if(!columnData[i].visible) {
				lastVisible--;
			} else {
				break;
			}
		}
		$.each(columnData, function(i, col) {
			col.field = col.title; //这样做是为了利用控件的机制实现若数据中字段名与模版不匹配则不显示数据

			if(options.editable) {
				if(col.disable || col.type == "file") {
					col.editable = false;
					return true;
				}

				var place = "bottom";
				if(col.visible && !firstVisibleFlag) {
					place = "right";
					firstVisibleFlag = true;
				}
				if(i == lastVisible) {
					place = "left";
				}

				col.editable = {
					mode: "popup",
					placement: place,
					type: col.type,
					emptytext: col.emptytext ? col.emptytext : options.defaultEmptyText,
					validate: function(value) {
						var $el = $(this);
						var msg;

						if(col.type == "date" || col.type == "datetime") {
							return {
								newValue: value
							};
						}

						//select2设置为多选的时候，去除掉不在枚举中的值
						if(col.type == "select2") {
							var v = value.split(',');
							if(v) {
								var newval = [];
								var source = that._columns.colSource[col.title];
								$.each(v, function(i, val) {
									if(val) {
										for(var k in source) {
											if(k === val) {
												newval.push(val);
											}
										}
									}
								});
								value = newval.join(',');
							}
						}

						$.each(columnData, function(key, val) {
							if(val.title == $el.attr("data-name")) {
								msg = vw_static.customValidate(columnData[key], value);
								return false;
							}
						});

						return {
							newValue: vw_static.getNoRepeat(value.split(',')).join(''),
							msg: msg
						};
					}
				};

				if(col.type == "text" || !col.type) {
					col.editable.display = function(value) {
						if(value == "undefined") {
							value = "";
							$(this).empty();
						} else {
							$(this).html(value);
						}
					}
				}

				if(col.type == "date") {
					col.editable.type = "combodate";
					col.editable.format = col.format ? col.format : options.dateFormat;
					col.editable.viewformat = options.viewDateFormat ? options.viewDateFormat : col.format;
					col.editable.template = 'YYYY 年 MM 月 DD 日';
					col.editable.combodate = {
						minYear: options.minYear,
						maxYear: options.maxYear,
						minuteStep: 1,
						smartDays: true,
						yearDescending: true,
						invalidDate: ""
					}
				}

				if(col.type == "datetime") {
					col.editable.type = "combodate";
					col.editable.format = col.format ? col.format : options.dateTimeFormat;
					col.editable.viewformat = options.viewDateTimeFormat ? options.viewDateTimeFormat : col.format;
					col.editable.template = 'YYYY 年 MM 月 DD 日  HH ：mm';
					col.editable.combodate = {
						minYear: options.minYear,
						maxYear: options.maxYear,
						minuteStep: 1,
						smartDays: true,
						yearDescending: true,
						invalidDate: ""
					}
				}

				if(col.type == "select" && col.source) {
					var source = that._columns.colSource[col.title];
					col.editable.source = [];
					for(var k in source) {
						col.editable.source.push({
							value: k,
							text: source[k]
						});
					}

					col.editable.display = function(value, sourceData) {
						if(!value && value !== 0) {
							$(this).html(value);
							return;
						}

						var subSource = selectSubSource(col.type, this, that._columns, $(this).parents('tbody'));
						if(!subSource.length) {
							subSource = sourceData;
						}

						var html = [];
						var checked = $.fn.editableutils.itemsByValue(value, subSource);
						if(checked.length) {
							$.each(checked, function(i, v) {
								html.push($.fn.editableutils.escape(v.text));
							});
							$(this).html(html.join(', '));
						} else {
							$(this).html(value);
						}
					}
				};

				if(col.type == "select2" && col.source) {
					var source = that._columns.colSource[col.title];
					col.editable.source = [];
					for(var k in source) {
						col.editable.source.push({
							id: k,
							text: source[k]
						});
					}

					col.editable.select2 = {
						placeholder: '请选择或输入关键字...',
						allowClear: true,
						minimumInputLength: 1,
						multiple: true
					};

					col.editable.display = function(value) {
						if(!value && value !== 0) {
							$(this).html(value);
							return;
						}

						var subSource = selectSubSource(col.type, this, that._columns, $(this).parents('tbody'));
						if(!subSource.length) {
							subSource = col.editable.source;
						}

						var checked = [];
						var html = [];
						var vals = value.toString().split(",");
						$.each(subSource, function(key, val) {
							if(vals.indexOf(val.id) != -1 && val.text) {
								checked.push(val);
							}
						});

						if(checked.length) {
							$.each(checked, function(i, v) {
								html.push($.fn.editableutils.escape(v.text));
							});
							$(this).html(html.join(', '));
						} else {
							$(this).html(value);
						}
					}
				}
			}
		});
	}

	function selectSubSource(coltype, element, columns, $control) {
		var dataName = $(element).attr('data-name');
		var row = $(element).attr('data-pk');
		var curCol;
		$.each(columns.data, function(k, col) {
			if(dataName == col.title) {
				curCol = col;
			}
		});

		var subSource = [];
		if(curCol.previouslink) {
			var upLevel = columns.colSource[curCol.previouslink];
			var upLevelText = $control.find('a[data-name="' + curCol.previouslink + '"][data-pk="' + row + '"]').text();
			var upLevelVal;
			$.each(upLevel, function(v, t) {
				if(t == upLevelText) {
					upLevelVal = v;
					return false;
				}
			});

			if(upLevelVal) {
				var attrName = coltype == "select" ? "text" : "id";
				$.each(curCol.source, function(i, item) {
					if(item.pid == upLevelVal) {
						var sourceItem = {};
						sourceItem[attrName] = item.text;
						sourceItem["value"] = item.id;
						subSource.push(sourceItem);
					}
				});
			}
		}
		return subSource;
	}

	function parseMath(obj, columnData, POSITION_SPLIT) {
		obj = JSON.parse(vw_static.SBCtoDBC(vw_static.uncompileStr(obj)));
		var ret = [];
		$.each(obj["expr"], function(index, item) {
			var expr = (obj["target"] + item).split(" ").join("");
			var exprText = expr;
			if(obj["target"].indexOf('[') != -1 && obj["target"].indexOf(']') != -1) {
				var scope = vw_static.getUniqueList(expr.match(/(?<=\[)(.+?)(?=\])/g));
				var matric = expr.match(/\[(\w+)\]:\[(\w+)\]/ig); //截取形如[A1]:[A3]
				if(matric) {
					$.each(matric, function(k, val) {
						var extent = val.match(/(?<=\[)(.+?)(?=\])/g);
						var s = getColumnRange(extent[0] + ":" + extent[1]);
						for(var i = 0; i < s.length; i++) {
							if(scope.indexOf(s[i]) == -1) {
								scope.push(s[i]);
							}
						}
						expr = expr.replace(val, s.join(','));
					});
				}
				expr = expr.split('[').join('');
				expr = expr.split(']').join('');

				ret.push({
					type: item[0],
					scope: scope,
					expr: expr,
					target: scope[0],
					text: exprText
				});
			} else if(obj["target"].indexOf('{') != -1 && obj["target"].indexOf('}') != -1) {
				var scopeText = vw_static.getUniqueList(expr.match(/(?<=\{)(.+?)(?=\})/g));
				var targetText = scopeText[0];
				var scope = {};
				$.each(columnData, function(k, val) {
					$.each(scopeText, function(i, v) {
						if(v == val.title) {
							scope[v] = val.cellposition.split(POSITION_SPLIT);
						}
					});
				});
				$.each(scope[targetText], function(k, val) {
					var thisScope = [];
					var thisExpr = expr;
					$.each(scope, function(name, value) {
						thisScope.push(value[k]);
						thisExpr = thisExpr.replace(name, value[k]);
						thisExpr = thisExpr.split('{').join('');
						thisExpr = thisExpr.split('}').join('');
					});
					ret.push({
						type: item[0],
						scope: thisScope,
						expr: thisExpr,
						target: val,
						text: exprText
					});
				});
			} else {}
		});
		return ret;
	}

	function getColumnRange(range) {
		var extent = range.split(":");
		var retval = [];
		if(extent.length == 1) {
			retval.push(range);
		} else if(extent.length == 2) {
			var row1 = parseInt(extent[1].replace(/[^0-9]/ig, ""));
			var row0 = parseInt(extent[0].replace(/[^0-9]/ig, ""));
			var col1 = extent[1].replace(/[0-9]/ig, "").charCodeAt();
			var col0 = extent[0].replace(/[0-9]/ig, "").charCodeAt();
			if(row0 == row1) {
				for(var i = col0; i <= col1; i++) {
					retval.push(String.fromCharCode(i) + row0);
				}
			} else if(col0 == col1) {
				for(var i = row0; i <= row1; i++) {
					retval.push(String.fromCharCode(col0) + i);
				}
			} else {
				for(var i = col0; i <= col1; i++) {
					for(var j = row0; j <= row1; j++) {
						retval.push(String.fromCharCode(i) + j);
					}
				}
			}
		} else {}
		return retval;
	}
};